package com.zystudio.func.net;



import com.zystudio.func.other.ZyLog;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;

public final class HttpExecutor {

    private static final class SingleTon {
        private static final HttpExecutor executor = new HttpExecutor();
    }

    public static HttpExecutor executor() {
        return SingleTon.executor;
    }

    private HttpExecutor() {}

    private static final int CATCH_CODE = -1;


    /**
     * get 请求
     *
     * @param urlString url地址
     * @param headers   请求头
     * @param callback  回调
     */
    public void get(final String urlString, final Map<String, String> headers, final IApiListener callback) {
        ThreadPoolManager.getInstance().execute(() -> {

            InputStream inputStream = null;
            try {
                URLConnection connection = buildCommonRequestProperties(urlString, headers);
                int responseCode = handleRequest(urlString, connection, "GET");
                //开始获取返回信息
                if (responseCode == 200) {
                    //网络请求成功
                    inputStream = connection.getInputStream();
                    parseResponseData(inputStream, callback);
                } else {
                    ZyLog.showLog("网络请求错误 ---> responseCode=" + responseCode);
                    if (callback != null) {
                        callback.onFailed(responseCode, "");
                    }
                }
            } catch (IOException exception) {
                if (callback != null) {
                    callback.onFailed(CATCH_CODE, exception.getMessage());
                }
            } finally {
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                } catch (IOException ex) {
                   ZyLog.showException("get URL", ex);
                }

            }
        });
    }

    /**
     * post请求
     *
     * @param urlString url地址
     * @param params    请求参数
     * @param headers   请求头
     * @param callback  回调
     */
    public void post(final String urlString, final String params, final Map<String, String> headers, final IApiListener callback) {
        ThreadPoolManager.getInstance().execute(() -> {
            InputStream inputStream = null;
            OutputStream outputStream = null;
            try {
                URLConnection connection = buildCommonRequestProperties(urlString, headers);
                connection.setDoInput(true);
                connection.setDoOutput(true);
                //写数据
                outputStream = connection.getOutputStream();
                outputStream.write(params.getBytes(StandardCharsets.UTF_8));
                outputStream.flush();
                //接收数据
                int responseCode = handleRequest(urlString, connection, "POST");
                if (responseCode == 200) {
                    //网络请求成功
                    inputStream = connection.getInputStream();
                    parseResponseData(inputStream, callback);
                } else {
                    ZyLog.showLog("网络请求错误 ---> responseCode=" + responseCode);
                    if (callback != null) {
                        callback.onFailed(responseCode, "");
                    }
                }
            } catch (IOException exception) {
                if (callback != null) {
                    callback.onFailed(CATCH_CODE, exception.getMessage());
                }
            } finally {
                try {
                    if (outputStream != null) {
                        outputStream.close();
                    }
                    if (inputStream != null) {
                        inputStream.close();
                    }
                } catch (IOException ex) {
                    ZyLog.showException("post URL", ex);
                }
            }
        });
    }

    private int handleRequest(String urlString, URLConnection connection, String Method) throws IOException {
        int responseCode;
        if (isHttps(urlString)) {
            HttpsURLConnection httpsURLConnection = (HttpsURLConnection) connection;
            httpsURLConnection.setHostnameVerifier(httpsHostNameVerifier);
            httpsURLConnection.setRequestMethod(Method);
            responseCode = httpsURLConnection.getResponseCode();
        } else {
            HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
            httpURLConnection.setRequestMethod(Method);
            responseCode = httpURLConnection.getResponseCode();
        }
        return responseCode;
    }

    private void parseResponseData(InputStream inputStream, IApiListener callback) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        int len;
        while ((len = inputStream.read(buf)) != -1) {
            bos.write(buf, 0, len);
        }
        bos.flush();
        if (callback != null) {
            callback.onSuccess(bos.toString("UTF-8"));
        }
    }

    private URLConnection buildCommonRequestProperties(String urlString, Map<String, String> headers) throws IOException {
        URL realUrl = new URL(urlString);
        URLConnection connection = realUrl.openConnection();
        //设置连接超时时间
        //网络超时时间
        int TIME_OUT = 4000;
        connection.setConnectTimeout(TIME_OUT);
        //设置读取超时时间
        connection.setReadTimeout(TIME_OUT);
        // 设置通用的请求属性
        connection.setRequestProperty("accept", "*/*");
        connection.setRequestProperty("connection", "Keep-Alive");
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
        connection.setRequestProperty("user-agent",
                "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36)");
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                connection.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
        connection.setUseCaches(false);
        return connection;
    }

    /**
     * 判断是否是HTTPS
     *
     * @param url：网络请求地址
     * @return true:HTTPS false:HTTP
     */
    private boolean isHttps(String url) {
        return url.trim().startsWith("https");
    }

    private final HostnameVerifier httpsHostNameVerifier = (hostname, session) -> {
        HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
        return hv.verify(hostname, session);
    };


}
